#-*- coding: utf8 -*-

from tutor.script import *
from tutor.plugin.maple import *
from tutor.plugin.math.functions import minimizer2D

# meta information
meta(author       = 'Fábio Mendes',
     creationdate = datetime(2010, 10, 23),
     status       = 'testing',
     difficulty   = 'easy',
     time         = 10,
     itemtype     = 'test')

# begin question
vars = [x, y]
shuffle(vars)
u, v = vars
t = M.t

# sorteia variáveis que definem a questão
a = oneof(1,-1) * oneof(2, M.sqrt(2), 2/M.sqrt(3))
print('parametro_a: ', a)

# define função
func = u**2 + v**2 + 4*u*a

# gradientes
grad_ok = [ diff(func, x), diff(func, y) ]
grad_e1 = [ diff(func - 4*a*u, x), diff(func - 4*a*u, y) ]
grads = [ grad_ok, grad_e1 ]

# soluções simples: grad_f = 0
sols = [ M.solve(grad, [x, y]) for grad in grads ]
sols = [ tuple(map(M.rhs, sol[0])) for sol in sols ]
f_values = [ M.evalf(subs(x==p[0], y==p[1], func)) for p in sols ]
print('Solucoes simples:', sols, f_values)

# soluções no disco: derivada direcional nula
dT1 = 2 * grad_ok[0] * (-sin(t)) + 2 * grad_ok[1] * cos(t) 
dT2 = 2 * grad_ok[0] * cos(t) + 2 * grad_ok[1] * sin(t)
dT1 = subs(x==2*cos(t), y==2*sin(t), dT1)
dT2 = subs(x==2*cos(t), y==2*sin(t), dT2)
dT_list = list(map(M.simplify, [dT1, dT2]))

# calcula parâmetro
sols_t = [ M.solve(dT, t) for dT in dT_list ]
sols_t = [ M.simplify(dT) for dT in sols_t ]
t1, t2 = sols_t
ans_d10 = (2*cos(t1), 2*sin(t1))
ans_d20 = (2*cos(t2), 2*sin(t2))
ans_d30 = (cos(t1), sin(t1))
ans_disc = [ ans_d10, ans_d20, ans_d30 ]

ans_d11 = (2*cos(t1 + M.Pi), 2*sin(t1 + M.Pi))
ans_d21 = (2*cos(t2 + M.Pi), 2*sin(t2 + M.Pi))
ans_d31 = (cos(t1 + M.Pi), sin(t1 + M.Pi))
ans_disc1 = [ ans_d11, ans_d21, ans_d31 ]

df_values = [ M.evalf(subs(x==p[0], y==p[1], func)) for p in ans_disc ]
df_values1 = [ M.evalf(subs(x==p[0], y==p[1], func)) for p in ans_disc1 ]
print('Solucoes no disco: ', dT_list, ans_disc, df_values)
print('Solucoes no disco: ', dT_list, ans_disc1, df_values1)

# calcula a resposta correta
if df_values[0] > df_values1[0]:
    ans_ok = ans_d10
    ans_half = ans_d11
else:
    ans_ok = ans_d11
    ans_half = ans_d10

# gradiente nulo
ans_grad = sols[0]

# circulo de raio 1
ans_small_circle = ans_d30

# erro na derivada direcional
ans_e_dirdiff = ans_d20

# ponto onde a função adquire o valor máximo
if a > 0:
    p = 2
else:
    p = -2
ans_max = (p, p)
 
question('Encontre o máximo global de \n\n    $$f(x,y) = ', func, '$$\n\n'
         'dentro de um círculo de raio $2$ centrado na origem.')
multiplechoice()

# choice: (a)
choice_eq(1, ans_ok) 
explanation('Escolha correta!') 

# choice: (b)
choice_eq(0.5, ans_half)
explanation('Existem dois pontos onde a derivada direcional se anula na região\n'
            'da borda. Você escolheu o ponto de \emph{mínimo} ao invés do de\n'
            '\emph{máximo}.') 

# choice: (c)
choice_eq(0, ans_small_circle)
explanation('Parametrização incorreta: escolheu um círculo de raio $1$.') 

# choice: (d)
choice_eq(0, ans_e_dirdiff)
explanation('Calculo errado da derivada direcional: lembre-se de derivar a\n'
            'parametrização por $t$ ao substituir na fórmula\n'
            '$\frac{df}{dt} = \frac{\partial f}{\partial x} \frac{dx}{dt} '
                           '+ \frac{\partial f}{\partial y} \frac{dy}{dt}$') 

# choice: (e)
choice_eq(0, ans_grad)
explanation('O ponto onde o gradiente se anula é um ponto de mínimo. Deveria '
            'testar a borda da região para encontrar o máximo.') 

# choice: (f)
choice_eq(0, ans_max)
explanation('Este ponto está fora do círculo. Foi escolhido para quem tentasse '
            'obter a resposta por substituição.') 

end()